package br.com.simora.cadastro;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.ResourceBundle;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.codec.binary.Base64;

import br.com.caelum.vraptor.Controller;
import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.Result;
import br.com.simora.component.PasswordEncryptionService;
import br.com.simora.controller.BasicController;
import br.com.simora.controller.HomeController;
import br.com.simora.usuario.Usuario;
import br.com.simora.usuario.UsuarioDAO;

@Controller
public class CadastroController extends BasicController {
    @Inject private UsuarioDAO usuarioDAO;
   
    public CadastroController(Result result, ResourceBundle bundle,
			UsuarioDAO usuarioDAO) {
    	this.result = result;
		this.bundle = bundle;
		this.usuarioDAO = usuarioDAO;
	}

    public CadastroController(){}
    
	@PostConstruct
    public void init(){
        injetaUsuario();
    }
   
    @Path(value = "/" + CADASTRO)
    @Get
    public void cadastro() {
    	result.include(CADASTRO, new Usuario());
        result.include("listaEstados", estados);
        result.include("plano", session.getPlano());
    }
    
    
    @Path(value = "/" + CADASTROMENSAL)
    public void cadastromensal() {
    	session.setPlano("Mensal");
    	result.redirectTo(CadastroController.class).cadastro();
    }
    
    @Path(value = "/" + CADASTROTRIMESTRAL)
    public void cadastrotrimestral() {
    	session.setPlano("Trimestral");
    	result.redirectTo(CadastroController.class).cadastro();
    }
    
    @Path(value = "/" + CADASTROANUAL)
    public void cadastroanual() {
    	session.setPlano("Anual");
    	result.redirectTo(CadastroController.class).cadastro();
    }
    
    @Path(value = "/" + CADASTRODEMO)
	public void cadastrodemo() {
    	session.setPlano("Tour Grátis de 1 dia");
    	session.setDemo(true);
    	result.redirectTo(CadastroController.class).cadastro();
    }
    
    
@Path(value = "/"  + CADASTRO + "/" + "gravarMeusDados")
    @Post
    public void gravarMeusDados(Usuario usuario){
	
		if(usuario == null)
			mensagemErro("erro.ao.gravar");
		else{
			usuarioDAO.update(usuario);
			mensagemSucesso("usuario.gravado.sucesso");
			result.redirectTo(HomeController.class).indexUsuario();
		}
    }
    
    @Path(value = "/"  + CADASTRO + "/" + GRAVAR)
    @Post
    public void gravar(Usuario usuario){
    	if(usuario == null)
    		mensagemErro("erro.ao.gravar");
    	
    	if(resultPossui(ERROR) && resultPossuiConteudo(ERROR)){ redirect(); return;}
        Usuario pre = usuarioDAO.recuperaUsuarioPorEmail(usuario.getEmail());
        if(pre != null){
            try {
                BeanUtils.copyProperties(pre, usuario);
            } catch (IllegalAccessException e) {
            	mensagemErro("erro.ao.gravar");
            } catch (InvocationTargetException e) {
            	mensagemErro("erro.ao.gravar");
            }
            
            mensagemErro("erro.email.existente");
            redirect();
            
        } else {
            usuario.setTipo("U");
            geraChaveCriptografada(usuario);
            
            if(session.isDemo()){
            	Calendar c = Calendar.getInstance(); 
            	Date dtExp = new Date();
                c.setTime(dtExp); 
                c.add(Calendar.DATE, 1);
                dtExp = c.getTime();
                usuario.setDataExpiracao(dtExp);
            }
            
            //TODO: CORRIGIR ISSO URGENTEMENTE!!
            usuario.setPlano(session.getPlano());
            if ("mensal".equalsIgnoreCase(session.getPlano()))
            	usuario.setValorContratado(new BigDecimal(500));
            else if ("trimestral".equalsIgnoreCase(session.getPlano()))
            	usuario.setValorContratado(new BigDecimal(400));
            else if ("anual".equalsIgnoreCase(session.getPlano()))
            	usuario.setValorContratado(new BigDecimal(300));
            else if ("tour grátis de 1 dia".equalsIgnoreCase(session.getPlano()))
            	usuario.setValorContratado(new BigDecimal(0));
            
            usuarioDAO.save(usuario);
            mensagemSucesso("usuario.gravado.sucesso");
            
			if(session.isDemo())
				redirectIndex();
			else
				redirectPagamento(usuario);
        }
    }
    
    
    @Path(value = "/"  + CADASTRO + "/" + "meusDados")
    @Get
    public void meusDados(){
    	Usuario uTemp = (Usuario)usuarioDAO.find(Usuario.class, session.getUsuario().getId());
    	result.include(USUARIO, uTemp);
    	result.include("listaEstados", estados);
    }
    
    @Path(value = "/"  + CADASTRO + "/" + "meuPlano")
    @Get
    public void meuPlano(){
    	Usuario uTemp = (Usuario)usuarioDAO.find(Usuario.class, session.getUsuario().getId());
    	result.include(USUARIO, uTemp);
    }
    
    @Path(value = "/"  + CADASTRO + "/" + PAGAR)
    @Get
    public void pagar(Usuario usuario){
    	result.include(USUARIO, usuario);
    }

	private void geraChaveCriptografada(Usuario usuario) {
		PasswordEncryptionService pes = new PasswordEncryptionService();
		
		try {
			byte[] salt = pes.generateSalt();
			usuario.setChave(Base64.encodeBase64String(salt));
			usuario.setSenha(Base64.encodeBase64String(pes.getEncryptedPassword(usuario.getSenha(), salt)));
		} catch (Exception e) {
			mensagemErro("erro.ao.gravar");
		}
	}
   

    protected void redirect() {
        result.redirectTo(CadastroController.class).cadastro();
    }
    
    protected void redirectPagamento(Usuario usuario) {
    	session.setDemo(false);
        result.redirectTo(CadastroController.class).pagar(usuario);
    }
    
    protected void redirectIndex() {
    	session.setDemo(false);
		result.redirectTo(HomeController.class).index();
	}

}